using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Framework.Extensions
{
    public static class FuncExtension
    {
        public static IEnumerable<T> Repeat<T>(this Func<T> createTFunc, int count)
        {
            while (count-- > 0)
            {
                yield return createTFunc();
            }
        }
        public static void Repeat(this Action action, int count)
        {
            while (count-- > 0)
            {
                action();
            }
        }
        public static Expression<Func<T, bool>> BuildAnd<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
        {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
        }

        public static string ToPath(this Expression source)
        {
            var result = string.Empty;
            var expressionType = source.GetType();
            if (source is LambdaExpression)
            {
                var body = ((LambdaExpression) source).Body;
                return body.ToPath();
            }
            if (source is MemberExpression)
            {
                var memberExpression = ((MemberExpression) source);
                var leftPath = memberExpression.Expression.ToPath();
                var rightPath = memberExpression.Member.Name;
                return leftPath.Maybe(z=> z + "." + rightPath, rightPath);
            }
            if (source is UnaryExpression)
            {
                return ((UnaryExpression) source).Operand.ToPath();
            }
            if (source is MethodCallExpression)
            {
                var methodCall = source as MethodCallExpression;
                foreach (var arg in methodCall.Arguments)
                {
                    var path = arg.ToPath();
                    if (!string.IsNullOrEmpty(path)) return path;
                }
            }
            return result;
        }

        public static string PropertyName<T, TProperty>(this T source, Expression<Func<T, TProperty>> propertyExpr)
        {
            return propertyExpr.ToPath();
        }

    }
}